//
//  NetworkManager.swift
//  SwiftNetwork
//
//  Created by 万孟超 on 2022/1/11.
//

import UIKit
import Alamofire

typealias NetworkCompleteBlock = (Any) -> Void
typealias NetworkErrorBlock = (Error) -> Void
typealias NetworkProgressBlock = (Progress) -> Void

class NetworkManager : NSObject {
    static func POST(withRequest request : NetworkBaseRequest,
                     wihEnginePoint enginePoint : String,
                     withProgressBlock progressBlock : NetworkProgressBlock? = nil,
                     withCompleteBlock completeBlock : NetworkCompleteBlock? = nil,
                     withErrorBlock errorBlock : NetworkErrorBlock? = nil) {
        let dataRequest = Alamofire.AF.request(request.methodUrl, method: .post, parameters: request.param)
        dataRequest.response { responseObj in
            do {
                if responseObj.error != nil {
                    if let error = responseObj.error {
                        var statusCode = responseObj.response?.statusCode
                        statusCode = dealError(error)
                        if statusCode == -1009 || statusCode == -1020 || statusCode == -1005 {
                            let retryModel = NetworkRetryModel.init(enginePoint: enginePoint, request: request, completeBlock: completeBlock, failBlock: errorBlock, progress: progressBlock)
                            NetworkClient.shared.addRetryNetwork(retryModel: retryModel)
                        }else if statusCode == -1001 && !request.isTimeOutRetry {
                            let retryModel = NetworkRetryModel.init(enginePoint: enginePoint, request: request, isTimeOutRetry: true, completeBlock: completeBlock, failBlock: errorBlock, progress: progressBlock)
                            NetworkClient.shared.addTimeOutRetryNetwork(retryModel: retryModel)
                        }else{
                            if errorBlock != nil {
                                errorBlock!(error)
                            }
                        }
                    }
                }else {
                    guard let data = responseObj.value! else {
                        return
                    }
                    NetworkClient.shared.removeEngineTask(forEnginePoint: enginePoint, isSuccess: true)
                    let jsonObj = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                    let result = jsonObj as! Dictionary<String,Any>
                    if completeBlock != nil {
                        completeBlock!(result)
                    }
                }
            }catch _ {
                
            }
        }
        NetworkClient.shared.addEngineTask(dataRequest, with: enginePoint)
    }
    
   static private func dealError(_ error : AFError) -> Int? {
        var statusCode : Int? = nil
        func dealReason(_ errorReason : AFError.ResponseValidationFailureReason) {
            switch errorReason {
            case .unacceptableStatusCode(let code):
                statusCode = code
            case .dataFileNil:
                print("1")
            case .dataFileReadFailed(at: _),
                 .missingContentType(acceptableContentTypes: _),
                 .unacceptableContentType(acceptableContentTypes: _, responseContentType: _):
                statusCode = nil
            case .customValidationFailed(error: let error):
                statusCode = error._code
            }
        }
        
        switch error {
        case .responseValidationFailed(let reason):
            dealReason(reason)
        case .createUploadableFailed(error: _),
                .createURLRequestFailed(error: _),
                .downloadedFileMoveFailed(error: _, source: _, destination: _),
                .explicitlyCancelled,
                .invalidURL(url: _),
                .multipartEncodingFailed(reason: _),
                .parameterEncodingFailed(reason: _),
                .parameterEncoderFailed(reason: _),
                .responseSerializationFailed(reason: _),
                .serverTrustEvaluationFailed(reason: _),
                .urlRequestValidationFailed(reason: _),
                .sessionDeinitialized:
            statusCode = nil
        case .requestAdaptationFailed(error: let tempError):
            statusCode = tempError._code
        case .requestRetryFailed(retryError: let retryError, originalError: _):
            statusCode = retryError._code
        case .sessionInvalidated(error: let tempError):
            statusCode = tempError?._code
        case .sessionTaskFailed(error: let tempError):
            statusCode = tempError._code
        }
        return statusCode
    }
}
